{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Distributed KernelSHAP"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "Note\n",
    "\n",
    "To enable SHAP support, you may need to run\n",
    "    \n",
    "```bash\n",
    "pip install alibi[shap]\n",
    "```\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example, KernelSHAP is used to explain a batch of instances on multiple cores. To run this example, please run ``pip install alibi[ray]`` first.\n",
    "\n",
    "<div class=\"alert alert-warning\">\n",
    "Warning\n",
    "\n",
    "Windows support for the `ray` Python library is [in beta](https://docs.ray.io/en/latest/ray-overview/installation.html#windows-support). Using `KernelShap` in parallel is not currently supported on Windows platforms.\n",
    "\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# shap.summary_plot currently doesn't work with matplotlib>=3.6.0,\n",
    "# see bug report: https://github.com/slundberg/shap/issues/2687\n",
    "!pip install matplotlib==3.5.3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pprint\n",
    "import shap\n",
    "import ray\n",
    "shap.initjs()\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "from alibi.explainers import KernelShap\n",
    "from alibi.datasets import fetch_adult\n",
    "from collections import defaultdict\n",
    "from scipy.special import logit\n",
    "from sklearn.compose import ColumnTransformer\n",
    "from sklearn.impute import SimpleImputer\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import accuracy_score, confusion_matrix, ConfusionMatrixDisplay\n",
    "from sklearn.model_selection import cross_val_score, train_test_split\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n",
    "from timeit import default_timer as timer\n",
    "from typing import Dict, List, Tuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data preparation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load and split"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `fetch_adult` function returns a `Bunch` object containing the features, the targets, the feature names and a mapping of categorical variables to numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['data', 'target', 'feature_names', 'target_names', 'category_map'])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "adult = fetch_adult()\n",
    "adult.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = adult.data\n",
    "target = adult.target\n",
    "target_names = adult.target_names\n",
    "feature_names = adult.feature_names\n",
    "category_map = adult.category_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that for your own datasets you can use our utility function `gen_category_map` to create the category map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from alibi.utils import gen_category_map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(0)\n",
    "data_perm = np.random.permutation(np.c_[data, target])\n",
    "data = data_perm[:,:-1]\n",
    "target = data_perm[:,-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "idx = 30000\n",
    "X_train,y_train = data[:idx,:], target[:idx]\n",
    "X_test, y_test = data[idx+1:,:], target[idx+1:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create feature transformation pipeline\n",
    "Create feature pre-processor. Needs to have 'fit' and 'transform' methods. Different types of pre-processing can be applied to all or part of the features. In the example below we will standardize ordinal features and apply one-hot-encoding to categorical features.\n",
    "\n",
    "Ordinal features:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "ordinal_features = [x for x in range(len(feature_names)) if x not in list(category_map.keys())]\n",
    "ordinal_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')),\n",
    "                                      ('scaler', StandardScaler())])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Categorical features:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "categorical_features = list(category_map.keys())\n",
    "categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')),\n",
    "                                          ('onehot', OneHotEncoder(drop='first', handle_unknown='error'))])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that in order to be able to interpret the coefficients corresponding to the categorical features, the option `drop='first'` has been passed to the `OneHotEncoder`. This means that for a categorical variable with `n` levels, the length of the code will be `n-1`. This is necessary in order to avoid introducing feature multicolinearity, which would skew the interpretation of the results. For more information about the issue about multicolinearity in the context of linear modelling see [[1]](#References).\n",
    "<a id='src_1'></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Combine and fit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {color: black;background-color: white;}#sk-container-id-1 pre{padding: 0;}#sk-container-id-1 div.sk-toggleable {background-color: white;}#sk-container-id-1 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-1 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-1 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-1 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-1 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-1 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-1 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-1 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-1 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-1 div.sk-item {position: relative;z-index: 1;}#sk-container-id-1 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-1 div.sk-item::before, #sk-container-id-1 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-1 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-1 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-1 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-1 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-1 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-1 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-1 div.sk-label-container {text-align: center;}#sk-container-id-1 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-1 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>ColumnTransformer(transformers=[(&#x27;num&#x27;,\n",
       "                                 Pipeline(steps=[(&#x27;imputer&#x27;,\n",
       "                                                  SimpleImputer(strategy=&#x27;median&#x27;)),\n",
       "                                                 (&#x27;scaler&#x27;, StandardScaler())]),\n",
       "                                 [0, 8, 9, 10]),\n",
       "                                (&#x27;cat&#x27;,\n",
       "                                 Pipeline(steps=[(&#x27;imputer&#x27;,\n",
       "                                                  SimpleImputer(strategy=&#x27;median&#x27;)),\n",
       "                                                 (&#x27;onehot&#x27;,\n",
       "                                                  OneHotEncoder(drop=&#x27;first&#x27;))]),\n",
       "                                 [1, 2, 3, 4, 5, 6, 7, 11])])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">ColumnTransformer</label><div class=\"sk-toggleable__content\"><pre>ColumnTransformer(transformers=[(&#x27;num&#x27;,\n",
       "                                 Pipeline(steps=[(&#x27;imputer&#x27;,\n",
       "                                                  SimpleImputer(strategy=&#x27;median&#x27;)),\n",
       "                                                 (&#x27;scaler&#x27;, StandardScaler())]),\n",
       "                                 [0, 8, 9, 10]),\n",
       "                                (&#x27;cat&#x27;,\n",
       "                                 Pipeline(steps=[(&#x27;imputer&#x27;,\n",
       "                                                  SimpleImputer(strategy=&#x27;median&#x27;)),\n",
       "                                                 (&#x27;onehot&#x27;,\n",
       "                                                  OneHotEncoder(drop=&#x27;first&#x27;))]),\n",
       "                                 [1, 2, 3, 4, 5, 6, 7, 11])])</pre></div></div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">num</label><div class=\"sk-toggleable__content\"><pre>[0, 8, 9, 10]</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">SimpleImputer</label><div class=\"sk-toggleable__content\"><pre>SimpleImputer(strategy=&#x27;median&#x27;)</pre></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">StandardScaler</label><div class=\"sk-toggleable__content\"><pre>StandardScaler()</pre></div></div></div></div></div></div></div></div><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">cat</label><div class=\"sk-toggleable__content\"><pre>[1, 2, 3, 4, 5, 6, 7, 11]</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-6\" type=\"checkbox\" ><label for=\"sk-estimator-id-6\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">SimpleImputer</label><div class=\"sk-toggleable__content\"><pre>SimpleImputer(strategy=&#x27;median&#x27;)</pre></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-7\" type=\"checkbox\" ><label for=\"sk-estimator-id-7\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">OneHotEncoder</label><div class=\"sk-toggleable__content\"><pre>OneHotEncoder(drop=&#x27;first&#x27;)</pre></div></div></div></div></div></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "ColumnTransformer(transformers=[('num',\n",
       "                                 Pipeline(steps=[('imputer',\n",
       "                                                  SimpleImputer(strategy='median')),\n",
       "                                                 ('scaler', StandardScaler())]),\n",
       "                                 [0, 8, 9, 10]),\n",
       "                                ('cat',\n",
       "                                 Pipeline(steps=[('imputer',\n",
       "                                                  SimpleImputer(strategy='median')),\n",
       "                                                 ('onehot',\n",
       "                                                  OneHotEncoder(drop='first'))]),\n",
       "                                 [1, 2, 3, 4, 5, 6, 7, 11])])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "preprocessor = ColumnTransformer(transformers=[('num', ordinal_transformer, ordinal_features),\n",
    "                                               ('cat', categorical_transformer, categorical_features)])\n",
    "preprocessor.fit(X_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Preprocess the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train_proc = preprocessor.transform(X_train)\n",
    "X_test_proc = preprocessor.transform(X_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Applying the `sklearn` processing pipeline modifies the column order of the original dataset. The new feature ordering is necessary in order to corectly plot visualisations, and is inferred from the `preprocessor` object below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "numerical_feats_idx  = preprocessor.transformers_[0][2]\n",
    "categorical_feats_idx  = preprocessor.transformers_[1][2]\n",
    "scaler = preprocessor.transformers_[0][1].named_steps['scaler']\n",
    "num_feats_names = [feature_names[i] for i in numerical_feats_idx]\n",
    "cat_feats_names = [feature_names[i] for i in categorical_feats_idx]\n",
    "perm_feat_names = num_feats_names + cat_feats_names "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original order:\n",
      "['Age',\n",
      " 'Workclass',\n",
      " 'Education',\n",
      " 'Marital Status',\n",
      " 'Occupation',\n",
      " 'Relationship',\n",
      " 'Race',\n",
      " 'Sex',\n",
      " 'Capital Gain',\n",
      " 'Capital Loss',\n",
      " 'Hours per week',\n",
      " 'Country']\n",
      "\n",
      "New features order:\n",
      "['Age',\n",
      " 'Capital Gain',\n",
      " 'Capital Loss',\n",
      " 'Hours per week',\n",
      " 'Workclass',\n",
      " 'Education',\n",
      " 'Marital Status',\n",
      " 'Occupation',\n",
      " 'Relationship',\n",
      " 'Race',\n",
      " 'Sex',\n",
      " 'Country']\n"
     ]
    }
   ],
   "source": [
    "pp = pprint.PrettyPrinter()\n",
    "print(\"Original order:\")\n",
    "pp.pprint(feature_names)\n",
    "print(\"\")\n",
    "print(\"New features order:\")\n",
    "pp.pprint(perm_feat_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a utility to reorder the columns of an input array so that the features have the same ordering as that induced by the preprocessor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def permute_columns(X: np.ndarray, feat_names: List[str], perm_feat_names: List[str]) -> np.ndarray:\n",
    "    \"\"\"\n",
    "    Permutes the original dataset so that its columns (ordered according to feat_names) have the order \n",
    "    of the variables after transformation with the sklearn preprocessing pipeline (perm_feat_names).\n",
    "    \"\"\"\n",
    "    \n",
    "    perm_X = np.zeros_like(X)\n",
    "    perm = []\n",
    "    for i, feat_name in enumerate(perm_feat_names):\n",
    "        feat_idx = feat_names.index(feat_name)\n",
    "        perm_X[:, i] = X[:, feat_idx]\n",
    "        perm.append(feat_idx)\n",
    "    return perm_X, perm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The categorical variables will be grouped to reduce shap values variance, as shown in [this](kernel_shap_adult_lr.ipynb) example. To do so, the dimensionality of each categorical variable is extracted from the preprocessor:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    feature_names  encoded_dim\n",
      "0       Workclass            8\n",
      "1       Education            6\n",
      "2  Marital Status            3\n",
      "3      Occupation            8\n",
      "4    Relationship            5\n",
      "5            Race            4\n",
      "6             Sex            1\n",
      "7         Country           10\n",
      "The dimensionality of the encoded categorical features is 45.\n"
     ]
    }
   ],
   "source": [
    "# get feature names for the encoded categorical features\n",
    "ohe = preprocessor.transformers_[1][1].named_steps['onehot']\n",
    "fts = [feature_names[x] for x in categorical_features]\n",
    "cat_enc_feat_names = ohe.get_feature_names_out(fts)\n",
    " # compute encoded dimension; -1 as ohe is setup with drop='first'\n",
    "feat_enc_dim = [len(cat_enc) - 1 for cat_enc in ohe.categories_]\n",
    "d = {'feature_names': fts , 'encoded_dim': feat_enc_dim}\n",
    "df = pd.DataFrame(data=d)\n",
    "print(df)\n",
    "total_dim = df['encoded_dim'].sum() \n",
    "print(\"The dimensionality of the encoded categorical features is {}.\".format(total_dim))\n",
    "assert total_dim == len(cat_enc_feat_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Select a subset of test instances to explain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def split_set(X, y, fraction, random_state=0):\n",
    "    \"\"\"\n",
    "    Given a set X, associated labels y, splits a fraction y from X.\n",
    "    \"\"\"\n",
    "    _, X_split, _, y_split = train_test_split(X, \n",
    "                                              y, \n",
    "                                              test_size=fraction, \n",
    "                                              random_state=random_state,\n",
    "                                             )\n",
    "    print(\"Number of records: {}\".format(X_split.shape[0]))\n",
    "    print(\"Number of class {}: {}\".format(0, len(y_split) - y_split.sum()))\n",
    "    print(\"Number of class {}: {}\".format(1, y_split.sum()))\n",
    "    \n",
    "    return X_split, y_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of records: 128\n",
      "Number of class 0: 96\n",
      "Number of class 1: 32\n"
     ]
    }
   ],
   "source": [
    "fraction_explained = 0.05 \n",
    "X_explain, y_explain = split_set(X_test, \n",
    "                                 y_test, \n",
    "                                 fraction_explained, \n",
    "                                 )\n",
    "X_explain_proc = preprocessor.transform(X_explain)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a version of the dataset to be explained that has the same feature ordering as that of the feature matrix after applying the preprocessing (for plotting purposes)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "perm_X_explain, _ = permute_columns(X_explain, feature_names, perm_feat_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fit a binary logistic regression classifier to the Adult dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Training "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LogisticRegression(max_iter=500, multi_class=&#x27;multinomial&#x27;, random_state=0)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-8\" type=\"checkbox\" checked><label for=\"sk-estimator-id-8\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">LogisticRegression</label><div class=\"sk-toggleable__content\"><pre>LogisticRegression(max_iter=500, multi_class=&#x27;multinomial&#x27;, random_state=0)</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "LogisticRegression(max_iter=500, multi_class='multinomial', random_state=0)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "classifier = LogisticRegression(multi_class='multinomial',\n",
    "                                random_state=0,\n",
    "                                max_iter=500,\n",
    "                                verbose=0,\n",
    "                               )\n",
    "classifier.fit(X_train_proc, y_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model assessment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = classifier.predict(X_test_proc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "cm = confusion_matrix(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "title = 'Confusion matrix for the logistic regression classifier'\n",
    "disp = ConfusionMatrixDisplay.from_estimator(classifier, \n",
    "                                             X_test_proc, \n",
    "                                             y_test,\n",
    "                                             display_labels=target_names,\n",
    "                                             cmap=plt.cm.Blues,\n",
    "                                             normalize=None,\n",
    "                                            )\n",
    "disp.ax_.set_title(title);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test accuracy:  0.855078125\n"
     ]
    }
   ],
   "source": [
    "print('Test accuracy: ', accuracy_score(y_test, classifier.predict(X_test_proc)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running KernelSHAP in sequential mode"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A background dataset is selected. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "start_example_idx = 0\n",
    "stop_example_idx = 100\n",
    "background_data = slice(start_example_idx, stop_example_idx)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Groups are specified by creating a list where each sublist contains the column indices that a given variable occupies in the preprocessed feature matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_groups(num_feats_names: List[str], cat_feats_names: List[str], feat_enc_dim: List[int]) -> Tuple[List[str], List[List[int]]]:\n",
    "    \"\"\"\n",
    "    Given a list with numerical feat. names, categorical feat. names\n",
    "    and a list specifying the lengths of the encoding for each cat.\n",
    "    varible, the function outputs a list of group names, and a list\n",
    "    of the same len where each entry represents the column indices that\n",
    "    the corresponding categorical feature \n",
    "    \"\"\"\n",
    "    \n",
    "    group_names = num_feats_names + cat_feats_names\n",
    "    groups = []\n",
    "    cat_var_idx = 0\n",
    "    \n",
    "    for name in group_names: \n",
    "        if name in num_feats_names:\n",
    "            groups.append(list(range(len(groups), len(groups) + 1)))\n",
    "        else:\n",
    "            start_idx = groups[-1][-1] + 1 if groups else 0\n",
    "            groups.append(list(range(start_idx, start_idx + feat_enc_dim[cat_var_idx] )))\n",
    "            cat_var_idx += 1\n",
    "    \n",
    "    return group_names, groups\n",
    "            \n",
    "def sparse2ndarray(mat, examples=None):\n",
    "    \"\"\"\n",
    "    Converts a scipy.sparse.csr.csr_matrix to a numpy.ndarray.\n",
    "    If specified, examples is slice object specifying which selects a\n",
    "    number of rows from mat and converts only the respective slice.\n",
    "    \"\"\"\n",
    "    \n",
    "    if examples:\n",
    "        return mat[examples, :].toarray()\n",
    "    \n",
    "    return mat.toarray()\n",
    "\n",
    "X_train_proc_d = sparse2ndarray(X_train_proc, examples=background_data)\n",
    "group_names, groups = make_groups(num_feats_names, cat_feats_names, feat_enc_dim)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initialise and run the explainer sequentially."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KernelShap(meta={\n",
       "  'name': 'KernelShap',\n",
       "  'type': ['blackbox'],\n",
       "  'task': 'classification',\n",
       "  'explanations': ['local', 'global'],\n",
       "  'params': {\n",
       "              'link': 'logit',\n",
       "              'group_names': ['Age', 'Capital Gain', 'Capital Loss', 'Hours per week', 'Workclass', 'Education', 'Marital Status', 'Occupation', 'Relationship', 'Race', 'Sex', 'Country'],\n",
       "              'grouped': True,\n",
       "              'groups': [[0], [1], [2], [3], [4, 5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17], [18, 19, 20], [21, 22, 23, 24, 25, 26, 27, 28], [29, 30, 31, 32, 33], [34, 35, 36, 37], [38], [39, 40, 41, 42, 43, 44, 45, 46, 47, 48]],\n",
       "              'weights': None,\n",
       "              'summarise_background': False,\n",
       "              'summarise_result': None,\n",
       "              'transpose': False,\n",
       "              'kwargs': {}}\n",
       "            ,\n",
       "  'version': '0.7.1dev'}\n",
       ")"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pred_fcn = classifier.predict_proba\n",
    "seq_lr_explainer = KernelShap(pred_fcn, link='logit', feature_names=perm_feat_names)\n",
    "seq_lr_explainer.fit(X_train_proc_d[background_data, :], group_names=group_names, groups=groups)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_runs = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "s_explanations, s_times = [], []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for run in range(n_runs):\n",
    "    t_start = timer()\n",
    "    explanation = seq_lr_explainer.explain(sparse2ndarray(X_explain_proc))\n",
    "    t_elapsed = timer() - t_start\n",
    "    s_times.append(t_elapsed)\n",
    "    s_explanations.append(explanation.shap_values)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running KernelSHAP in distributed mode"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The only change needed to distribute the computation is to pass a dictionary containing the number of (physical) CPUs available to distribute the computation to the `KernelShap` constructor:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def distrib_opts_factory(n_cpus: int) -> Dict[str, int]:\n",
    "    return {'n_cpus': n_cpus}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpu_range = range(2, 5)\n",
    "distrib_avg_times = dict(zip(cpu_range, [0.0]*len(cpu_range)))\n",
    "distrib_min_times = dict(zip(cpu_range, [0.0]*len(cpu_range))) \n",
    "distrib_max_times = dict(zip(cpu_range, [0.0]*len(cpu_range))) \n",
    "d_explanations = defaultdict(list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for n_cpu in cpu_range:\n",
    "    opts = distrib_opts_factory(n_cpu)\n",
    "    distrib_lr_explainer = KernelShap(pred_fcn, link='logit', feature_names=perm_feat_names, distributed_opts=opts)\n",
    "    distrib_lr_explainer.fit(X_train_proc_d[background_data, :], group_names=group_names, groups=groups)\n",
    "    raw_times = []\n",
    "    for _ in range(n_runs):\n",
    "        t_start = timer()\n",
    "        d_explanations[n_cpu].append(distrib_lr_explainer.explain(sparse2ndarray(X_explain_proc), silent=True).shap_values)\n",
    "        t_elapsed = timer() - t_start\n",
    "        raw_times.append(t_elapsed)\n",
    "    distrib_avg_times[n_cpu] = np.round(np.mean(raw_times), 3)\n",
    "    distrib_min_times[n_cpu] = np.round(np.min(raw_times), 3)\n",
    "    distrib_max_times[n_cpu] = np.round(np.max(raw_times), 3)\n",
    "    ray.shutdown()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Results analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Timing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Distributed average times for 3 runs (n_cpus: avg_time):\n",
      "{2: 57.197, 3: 41.728, 4: 36.751}\n",
      "\n",
      "Sequential average time for 3 runs:\n",
      "119.656 s\n"
     ]
    }
   ],
   "source": [
    "print(f\"Distributed average times for {n_runs} runs (n_cpus: avg_time):\")\n",
    "print(distrib_avg_times)\n",
    "print(\"\")\n",
    "print(f\"Sequential average time for {n_runs} runs:\")\n",
    "print(np.round(np.mean(s_times), 3), \"s\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Running KernelSHAP in a distributed fashion improves the runtime as the results above show. However, the results above should not be interpreted as performance measurements since they were not run in a controlled environment. See our [blog post](https://www.seldon.io/how-seldons-alibi-and-ray-make-model-explainability-easy-and-scalable/) for a more thorough analysis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explanations comparison"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "cls = 0  # class of prediction explained\n",
    "run = 1  # which run to compare the result for"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x453.6 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# sequential\n",
    "shap.summary_plot(s_explanations[run][cls], perm_X_explain, perm_feat_names)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x453.6 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# distributed\n",
    "n_cpu = 3\n",
    "shap.summary_plot(d_explanations[n_cpu][run][cls], perm_X_explain, perm_feat_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparing the results above one sees that the running the algorithm across multiple cores gave identical results, indicating its correctness."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This example showed that batches of explanations can be explained much faster by simply passing ``distributed_opts={'n_cpus': k}`` to the ``KernelShap`` constructor (here ``k`` is the number of physical cores available). The significant runtime reduction makes it possible to explain larger datasets faster and combine shap values estimated with KernelSHAP into global explanations or use larger background datasets."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
